package whu.edu.assingment6.Aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

/**
 * @author guanruwang
 * @date 2023/10/25$
 */
@Slf4j
@Aspect
@Component
public class AopAspect {

    Map<String,Integer> countMap = new HashMap<>();
    Map<String,Long> minMap = new HashMap<>();
    Map<String,Long> maxMap = new HashMap<>();
    Map<String,Long> avgMap = new HashMap<>();

    Map<String,Integer> exMap = new HashMap<>();

    @Pointcut(value ="@annotation(whu.edu.assingment6.Aspect.count)")
    public void controllerPointCut(){ }

    @After(value = "controllerPointCut()")
    public void After(JoinPoint joinPoint){
        String name = joinPoint.getSignature().toString();
        if(countMap.containsKey(name)){
            countMap.put(name,countMap.get(name)+1);
        }else{
            countMap.put(name,1);
        }
    }

    @AfterThrowing(value = "controllerPointCut()",throwing = "ex")
    public void afterPointCutThrow(JoinPoint joinPoint,Throwable ex){
        String name = joinPoint.getSignature().toString();
        if(exMap.containsKey(name)){
            exMap.put(name,exMap.get(name)+1);
        }else{
            exMap.put(name,1);
        }

    }



    @Around("execution(* whu.edu.assingment6.controller.*.*(..))")
    public Object Around(ProceedingJoinPoint joinPoint) throws Throwable {
        long t1= Calendar.getInstance().getTimeInMillis();
        Object retValue = joinPoint.proceed();
        long t2= Calendar.getInstance().getTimeInMillis();
        String methodSig=joinPoint.getSignature().toString();
        long time = t2-t1;
        if(minMap.containsKey(methodSig)) {
            if (minMap.get(methodSig) > time) {
                minMap.put(methodSig, time);
            }
        }else{
            minMap.put(methodSig,time);
        }

        if(maxMap.containsKey(methodSig)) {
            if (maxMap.get(methodSig) < time) {
                maxMap.put(methodSig, time);
            }
        }else{
            maxMap.put(methodSig,time);
        }

        if(avgMap.containsKey(methodSig)) {
            avgMap.put(methodSig, (avgMap.get(methodSig) + time) / (countMap.get(methodSig) + 1));
        }else{
            avgMap.put(methodSig,time);
        }
        log.info("");

        return retValue;
    }

    public void print(){
        log.info("countMap:{}",countMap.toString());
        log.info("minMap:{}",minMap.toString());
        log.info("maxMap:{}",maxMap.toString());
        log.info("avgMap:{}",avgMap.toString());
        log.info("exMap:{}",exMap.toString());
    }

}
